#include "helper/sqlite/Value.h"

#include <sqlite3.h>
#include <cstring>
#include <cassert>

namespace helper {
namespace sqlite {

Value::Value(void * stmt, int index) 
: _stmt(stmt)
, _index(index)
{
}
Value::~Value(){
}

bool Value::isNull() const{
  assert(_stmt != nullptr);
  return sqlite3_column_type(static_cast<sqlite3_stmt*>(_stmt), _index) == SQLITE_NULL;
}
bool Value::isInteger() const{
  assert(_stmt != nullptr);
  return sqlite3_column_type(static_cast<sqlite3_stmt*>(_stmt), _index) == SQLITE_INTEGER;
}
bool Value::isReal() const{
  assert(_stmt != nullptr);
  return sqlite3_column_type(static_cast<sqlite3_stmt*>(_stmt), _index) == SQLITE_FLOAT;
}
bool Value::isString() const{
  assert(_stmt != nullptr);
  return sqlite3_column_type(static_cast<sqlite3_stmt*>(_stmt), _index) == SQLITE_TEXT;
}
bool Value::isBinary() const{
  assert(_stmt != nullptr);
  return sqlite3_column_type(static_cast<sqlite3_stmt*>(_stmt), _index) == SQLITE_BLOB;
}

int64_t Value::length() const{
  assert(_stmt != nullptr);
  return sqlite3_column_bytes(static_cast<sqlite3_stmt*>(_stmt), _index);
}

int64_t Value::integer() const{
  assert(_stmt != nullptr);
  return sqlite3_column_int64(static_cast<sqlite3_stmt*>(_stmt), _index);
}
double Value::real() const{
  assert(_stmt != nullptr);
  return sqlite3_column_double(static_cast<sqlite3_stmt*>(_stmt), _index);
}
std::string Value::string() const{
  assert(_stmt != nullptr);
  return std::string(reinterpret_cast<const char *>(sqlite3_column_text(static_cast<sqlite3_stmt*>(_stmt), _index)), length());
}
void Value::string(std::string & str) const {
  assert(_stmt != nullptr);
  str.append(reinterpret_cast<const char *>(sqlite3_column_text(static_cast<sqlite3_stmt*>(_stmt), _index)), length());
}
size_t Value::string(char * buf, size_t len) const {
  assert(_stmt != nullptr);
  const char * text = reinterpret_cast<const char *>(sqlite3_column_text(static_cast<sqlite3_stmt*>(_stmt), _index));
  size_t text_len = (size_t)length();
  
  if(len >= text_len){
    std::memcpy(buf, text, text_len);
    return text_len;
  }
  std::memcpy(buf, text, len);
  return len;
}

std::string Value::binary() const{
  assert(_stmt != nullptr);
  return std::string( static_cast<const char *>(sqlite3_column_blob(static_cast<sqlite3_stmt*>(_stmt), _index)), length());
}
void Value::binary(std::string & str ) const {
  assert(_stmt != nullptr);
  str.append(static_cast<const char *>(sqlite3_column_blob(static_cast<sqlite3_stmt*>(_stmt), _index)), length());
}
size_t Value::binary(char * buf, size_t len) const {
  assert(_stmt != nullptr);
  const void * text = sqlite3_column_blob(static_cast<sqlite3_stmt*>(_stmt), _index);
  size_t text_len = (size_t)length();
  
  if(len >= text_len){
    std::memcpy(buf, text, text_len);
    return text_len;
  }
  std::memcpy(buf, text, len);
  return len;
}

}//namespace sqlite
}//namespace helper
